﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BadHabit.Factory {

    
   
    public partial class Factory {

        private static Data.TaskDataSetTableAdapters.TaskTailTableAdapter taskTailAD = new BadHabit.Factory.Data.TaskDataSetTableAdapters.TaskTailTableAdapter();
        private static Data.TaskDataSetTableAdapters.TaskTailImpactedItemTableAdapter taskTailImpactedItemAD = new BadHabit.Factory.Data.TaskDataSetTableAdapters.TaskTailImpactedItemTableAdapter();
        private static Data.TaskDataSetTableAdapters.TaskTableAdapter taskAD = new BadHabit.Factory.Data.TaskDataSetTableAdapters.TaskTableAdapter();

               

        /// <summary>
        /// Creates a tail between a given team member and a group of artifacts.
        /// It detects what is the task that the team member is current working to tail it.
        /// </summary>
        /// <param name="repositoryURL">The Artifact repository URL</param>
        /// <param name="teamMember">The team member</param>
        /// <param name="artifactsPath">The modified artifacts</param>
        /// <param name="revision">The revision number</param>
        public Data.TaskDataSet TailTaskByTeamMember(string repositoryURL, string teamMember, string[] artifactsPath, int revision) {

            string taskUId = GetWorkingTaskUIdByTeamMember(teamMember);
            if (taskUId == null || taskUId.Trim().Equals(Guid.Empty.ToString()))
                throw new Exception("Can´t tail task. " + teamMember + " is not working at any task now.");
            TailArtifacts(repositoryURL, taskUId, artifactsPath, revision, true);

            Data.TaskDataSet dsTask = new BadHabit.Factory.Data.TaskDataSet();
            taskAD.FillByTaskUId(dsTask.Task, taskUId);

            return dsTask;
            
        }

        
        /// <summary>
        /// Creates a tail between a given task and a group of artifacts.
        /// </summary>
        /// <param name="repositoryURL">The Artifact repository URL</param>
        /// <param name="taskId">The taskId</param>
        /// <param name="artifactsPath">The modified artifacts</param>
        /// <param name="revision">The revision number</param>
        public Data.TaskDataSet TailTaskById(string repositoryURL, int taskId, string[] artifactsPath, int revision) {
            Data.TaskDataSet dsTask = new BadHabit.Factory.Data.TaskDataSet();

            
            string taskUId = null;
            taskAD.FillByTaskId(dsTask.Task, taskId);
            
            if(dsTask.Task.Rows.Count==0)
                throw new Exception("Task " + taskId + " was not found.");

            taskUId = dsTask.Task[0].TaskUId;

            TailArtifacts(repositoryURL, taskUId, artifactsPath, revision, true);

            
            return dsTask;

                       
            
        }

        private void TailArtifacts(string repositoryURL, string taskUId, string[] artifactsPath, int revision, bool isSourceControled) {
            Data.TaskDataSet dsTask = new BadHabit.Factory.Data.TaskDataSet();

            foreach (string artifact in artifactsPath) {
                string extension = GetArtifactExtension(artifact);
                if(!extension.Equals(string.Empty))
                    taskTailAD.TailTaskByTaskUId(
                        Guid.NewGuid().ToString().ToLower(),
                        taskUId,
                        artifact,
                        revision,
                        extension,
                        DateTime.Now,
                        repositoryURL,
                        isSourceControled);
            }

        }

        public void TailTaskMaterial(string taskUId, string[] materialPath) {            
            TailArtifacts("", taskUId, materialPath, 0, false);
        }

        

        


        public void DeleteTaskTail(string taskTailUId) {
            taskTailAD.DeleteByTaskTailUId(taskTailUId);
        }

        public void DeleteTaskTail(string backlogItemUId, string artifactPath) {
            taskTailAD.DeleteByArtifactPathAndBacklogItemUId(artifactPath, backlogItemUId);
        }


        


        /// <summary>
        /// Gets a artifact file extension.
        /// </summary>
        /// <param name="artifactPath">The artifact path</param>
        /// <returns>The file extension</returns>
        private static string GetArtifactExtension(string artifactPath) {

            string artifactName = artifactPath;

            if (artifactPath.Contains('/'))
                artifactName = artifactPath.Substring(artifactPath.LastIndexOf('/'));

            if (artifactName.IndexOf('.') == -1)
                return String.Empty;

            return artifactName.Substring(artifactName.IndexOf('.'));
        }
        
        private string GetArtifactName(string artifactPath) {
            if (artifactPath == null)
                return String.Empty;
            artifactPath = artifactPath.Replace("\\", "/");
            int lastIndex = artifactPath.LastIndexOf('/');
            if (lastIndex < 0)
                return String.Empty;
            return artifactPath.Substring(lastIndex + 1);

        }


        public Data.TaskDataSet RetriveArtifactsByTaskUId(string taskUId) {

            // first retrives the tailed tasks
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailAD.FillByTaskUId(ds.TaskTail, taskUId);

            // now tries to find the cycle definition
            Data.CycleDefinitionDataSet dsCycle = null;
            if (ds.TaskTail.Count > 0) {
                try {
                    Data.ProjectDataSet dsProject = RetriveProject(ds.TaskTail[0].ProjectUId);
                    if (dsProject.Project.Count > 0) {
                        dsCycle = RetriveCycleDefinition(dsProject.Project[0].Category);
                    }
                } catch (Exception) { }
            }

            // fills the cycle information
            FillCycleInformation(ds.TaskTail, dsCycle);
                
            return ds;
        }

        public Data.TaskDataSet RetriveArtifactsByBacklogItemUId(string backlogItemUId, string projectCategory) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailAD.FillByBacklogItemUId(ds.TaskTail, backlogItemUId);

            // reads the project cycle information
            Data.CycleDefinitionDataSet dsCycle = null;
            try {                
                dsCycle = RetriveCycleDefinition(projectCategory);                                
            } catch (Exception) { }

            FillCycleInformation(ds.TaskTail, dsCycle);
            

            return ds;
        }

        public Data.TaskDataSet RetriveArtifactsByProjectUId(string projectUId, string projectCategory) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailAD.FillArtifactsByProjectUId(ds.TaskTail, projectUId);

            // reads the project cycle information
            Data.CycleDefinitionDataSet dsCycle = null;
            try {
                dsCycle = RetriveCycleDefinition(projectCategory);
            } catch (Exception) { }

            FillCycleInformation(ds.TaskTail, dsCycle);


            return ds;
        }

        public Data.TaskDataSet RetriveTailsByProjectUId(string projectUId, string projectCategory) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailAD.FillByProjectUId(ds.TaskTail, projectUId);

            // reads the project cycle information
            Data.CycleDefinitionDataSet dsCycle = null;
            try {
                dsCycle = RetriveCycleDefinition(projectCategory);
            } catch (Exception) { }

            FillCycleInformation(ds.TaskTail, dsCycle);


            return ds;
        }


        

        public Data.TaskDataSet RetriveImpactedItemsByProjectUId(string projectUId) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailImpactedItemAD.FillByProjectUId(ds.TaskTailImpactedItem, projectUId);
            return ds;
        }

        public Data.TaskDataSet RetriveImpactedItemsByTaskUId(string taskUId) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailImpactedItemAD.FillByTaskUId(ds.TaskTailImpactedItem, taskUId);
            return ds;
        }

        public Data.TaskDataSet RetriveImpactedItemsByTailUId(string tailUId) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailImpactedItemAD.FillByTailUId(ds.TaskTailImpactedItem, tailUId);
            return ds;
        }

        public Data.TaskDataSet RetriveImpactedItemsByBacklogItemUId(string backlogItemUId) {
            Data.TaskDataSet ds = new BadHabit.Factory.Data.TaskDataSet();
            taskTailImpactedItemAD.FillBySourceBacklogItemUId(ds.TaskTailImpactedItem, backlogItemUId);
            return ds;
        }

        public Data.TaskDataSet RetriveTasksByTailedBacklogItemUId(string backlogItemUId) {
            Data.TaskDataSet task = new BadHabit.Factory.Data.TaskDataSet();
            taskResumeTA.FillByTailedBacklogItemUId(task.TaskResume, backlogItemUId);
            return task;
        }

        public Data.TaskDataSet RetriveTasksByTailedProjectUId(string projectUId) {
            Data.TaskDataSet task = new BadHabit.Factory.Data.TaskDataSet();
            taskResumeTA.FillByTailedProjectUId(task.TaskResume, projectUId);
            return task;
        }

        public Data.TaskDataSet RetriveTasksByTailUId(string tailUId) {
            Data.TaskDataSet task = new BadHabit.Factory.Data.TaskDataSet();
            taskResumeTA.FillByTailUId(task.TaskResume, tailUId);
            return task;
        }

        public Data.TaskDataSet RetriveTasksByArtifactPath(string artifactPath) {
            Data.TaskDataSet task = new BadHabit.Factory.Data.TaskDataSet();
            taskResumeTA.FillByArtifactPath(task.TaskResume, artifactPath);
            return task;
        }


        public Data.CycleDefinitionDataSet RetriveCycleDefinition(string projectCategory) {
            // read the project from the XML template file
            Data.CycleDefinitionDataSet dsCycle = new Data.CycleDefinitionDataSet();
            string path = ServerPath + @"\App_Data\ProjectTemplates\" + projectCategory + @"\CycleDefinition.xml";
            dsCycle.ReadXml(path);
            return dsCycle;
        }


        /// <summary>
        /// Fills the cycle infomration at the task tail table.
        /// </summary>
        /// <param name="tailTable">The taskTail Table</param>
        /// <param name="cycleDefinition">The cycle definition</param>
        public void FillCycleInformation(Data.TaskDataSet.TaskTailDataTable tailTable, Data.CycleDefinitionDataSet cycleDefinition) {

            // now for every, artifact, fill its value
            foreach (Data.TaskDataSet.TaskTailRow tail in tailTable) {                
                tail.ArtifactName = GetArtifactName(tail.ArtifactPath);
                tail.ArtifactGroup = "Unknow Artifacts";
                tail.ActivityName = "Unknow Sprint Activity";
                tail.ActivityOrder = 1000;

                if (cycleDefinition != null) {

                    
                    Data.CycleDefinitionDataSet.ArtifactRow artifactDef = FindArtifactDefinitionForTail(tail, cycleDefinition);
                    if (artifactDef != null) {
                        tail.ActivityName = artifactDef.ActivityName;
                        tail.ActivityOrder = artifactDef.SprintFaseRow.ActivityOrder;
                        tail.ArtifactGroup = artifactDef.ArtifactGroup;    
                        if(!artifactDef.IsTypeNull())
                            tail.ArtifactGroupType = artifactDef.Type;
                    }
                }
            }


        }

       

        private Data.CycleDefinitionDataSet.ArtifactRow FindArtifactDefinitionForTail(Data.TaskDataSet.TaskTailRow tail, Data.CycleDefinitionDataSet cycleDefinition) {

            // verifies all artifacts definition to see what one is it
            foreach (Data.CycleDefinitionDataSet.ArtifactRow artifactDef in cycleDefinition.Artifact) {

                // first check the startwidth rule
                if (!artifactDef.IsStartsWithRuleNull() && tail["ArtifactName"].ToString().StartsWith(artifactDef.StartsWithRule))
                    return artifactDef;

                // then check the extension rules
                if (!artifactDef.IsExtentionRuleNull() && IsAtExtensionRule(tail.ArtifactExtension, artifactDef.ExtentionRule))
                    return artifactDef;
            }

            return null;
        }


        private bool IsAtExtensionRule(string ext, string rule) {
            string[] extArray = rule.Split(' ');
            for (int i = 0; i < extArray.Length; i++)
                if (ext.ToLower().Equals(extArray[i].ToLower()))
                    return true;
            return false;

        }



    }
}
